import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.Buffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class Parser {
    //指定文档文件的路径
    private static final String FILE_PATH = "D:/桌面/jdk-17.0.11_doc-all/docs/api";

    private Index index = new Index();

    private AtomicLong parserHTMLTime = new AtomicLong(0);
    private AtomicLong addDocTime = new AtomicLong(0);
    public static void main(String[] args) throws InterruptedException {
        Parser p = new Parser();
        p.parserByThread();
    }
    private void parserByThread() throws InterruptedException {
        long beg = System.currentTimeMillis();
        System.out.println("开始制作索引");
        //1.找出所有html文件
        List<File> fileList = new ArrayList<>();
        enumFile(FILE_PATH, fileList);

        long end1 = System.currentTimeMillis();
        System.out.println("枚举文件所用时间：" + (end1 - beg) + "ms");

        //2.使用线程词并发对每个HTML文件进行解析并制作索引
        CountDownLatch countDownLatch = new CountDownLatch(fileList.size());
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        for(File f : fileList) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("开始解析：" + f.getAbsolutePath());
                    parserHTML(f);
                    countDownLatch.countDown();
                }
            });
        }

        //等待所有任务执行完成
        countDownLatch.await();

        executorService.shutdown();

        long end2 = System.currentTimeMillis();
        System.out.println("解析和添加索引消耗时间：" + (end2 - end1) + "ms");

        //3.把索引文件保存到磁盘
        index.save();

        long end3 = System.currentTimeMillis();
        System.out.println("保存索引消耗时间：" + (end3 - end2) + "ms");

        long end4 = System.currentTimeMillis();
        System.out.println("索引制作消耗总时间：" + (end4 - beg) + "ms");

        System.out.println("解析HTML消耗时间：" + parserHTMLTime.get() / 1000_000 + "ms");
        System.out.println("addDoc消耗时间：" + addDocTime.get() / 1000_000 + "ms");

    }
    //解析文档
    private void parser() {
        long beg = System.currentTimeMillis();
        System.out.println("开始制作索引");
        //1.找出所有html文件
        List<File> fileList = new ArrayList<>();
        enumFile(FILE_PATH, fileList);

        long end1 = System.currentTimeMillis();
        System.out.println("枚举文件所用时间：" + (end1 - beg) + "ms");

        //2.对每个HTML文件进行解析并制作索引
       for(File f : fileList) {
           System.out.println("开始解析：" + f.getAbsolutePath());
           parserHTML(f);
       }

       long end2 = System.currentTimeMillis();
        System.out.println("解析和添加索引消耗时间：" + (end2 - end1) + "ms");

       //3.把索引文件保存到磁盘
        index.save();

        long end3 = System.currentTimeMillis();
        System.out.println("保存索引完成，消耗时间：" + (end3 - end2) + "ms");

        long end4 = System.currentTimeMillis();
        System.out.println("索引制作完成,消耗总时间：" + (end4 - beg) + "ms");
    }

    private void parserHTML(File file) {
        long beg = System.nanoTime();
        //a.解析出标题
        String title = parserTitle(file);

        //b.解析出url
        String url = parserUrl(file);

        //c.解析出正文
        String content = parserContent(file);
        long end1 = System.nanoTime();
        parserHTMLTime.addAndGet(end1 - beg);

        //d.添加索引
        index.addDoc(title, url, content);
        long end2 = System.nanoTime();
        addDocTime.addAndGet(end2 - end1);
    }

    private String parserContent(File file) {
        StringBuilder content = new StringBuilder();
        //按字节读,这里使用BufferedReader 提高速度
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file), 1024 * 1024)) {
            while(true) {
                int ch = bufferedReader.read();
                if(ch == -1) {
                    //文件读完了
                    break;
                }
                content.append((char)ch);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String ret = content.toString();

        //使用正则表达式替换掉js代码
        ret = ret.replaceAll("<script.*?>.*?</script>", "");
        //使用正则表达式替换html标签
        ret = ret.replaceAll("<.*?>", "");
        //把连续的多个空格替换为一个空格
        ret = ret.replaceAll("\\s+", " ");

        return ret;
    }

    private String parserUrl(File file) {
        //https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/javax/sound/sampled/AudioFormat.html
        //D:/%E6%A1%8C%E9%9D%A2/jdk-17.0.11_doc-all/docs/api/java.desktop/javax/sound/sampled/AudioFormat.html
        String s1 = "https://docs.oracle.com/en/java/javase/17/docs/api";
        String s2 = file.getAbsolutePath().substring(FILE_PATH.length()).replace("\\", "/");
        return s1 + s2;
    }

    private String parserTitle(File file) {
        String fileName = file.getName();
        return fileName.substring(0, fileName.length() - ".html".length());
    }

    private void enumFile(String filePath, List<File> fileList) {
        File file = new File(filePath);
        //获取目录下的文件列表
        File[] files = file.listFiles();
        for(File f : files) {
            if(f.isDirectory()) {
                //如果f是目录则递归添加文件
                enumFile(f.getAbsolutePath(), fileList);
            }else if(f.getName().endsWith(".html")){
                //如果f是html文件则添加到fileList中
                fileList.add(f);
            }
        }
    }
}
